using System.Collections.Generic;

namespace Box {
    public enum ProcessTreeNodePortStatus {
        Low,
        High,
    }

    public class ProcessNode {
        public ProcessTree Tree;
        public Dictionary<string,ProcessNodePort> Ports = new Dictionary<string, ProcessNodePort>();
        public virtual void onInputHigh(string from_port) {}
        public virtual void onInputLow(string from_port){}
        public virtual (string,ProcessTreeNodePortType)[] GetPortsDefines() { return null;}

        public ProcessNode() {
            var ports = GetPortsDefines();
            foreach((string,ProcessTreeNodePortType) define in ports) {
                ProcessNodePort port = new ProcessNodePort();
                port.Name = define.Item1;
                port.Type = define.Item2;
                port.Node = this;
                Ports[port.Name] = port;
            }
        }

        public ProcessNodePort GetPort(string name) {
            if(!Ports.ContainsKey(name)) return null;
            return Ports[name];
        }

        protected void onInput(string from_port,ProcessTreeNodePortStatus status) {
            if(status == ProcessTreeNodePortStatus.High) {
                onInputHigh(from_port);
            } else {
                onInputLow(from_port);
            }
        }

        public void Output(string port_name,ProcessTreeNodePortStatus status) {
            ProcessNodePort port;
            if(Ports.TryGetValue(port_name,out port)) {
                if(status == ProcessTreeNodePortStatus.High) {
                    foreach(var child in port.Children.Values) {
                        child.Node.onInputHigh(child.Name);
                    }
                } else {
                    foreach(var child in port.Children.Values) {
                        child.Node.onInputLow(child.Name);
                    }
                }
            }
        }

        public void Connect(string out_port_name,ProcessNode node,string in_port_name) {
            var out_port = GetPort(out_port_name);
            var in_port = node.GetPort(in_port_name);
            if(out_port == null || in_port == null) return;
            out_port.AddChild(in_port);
        }

        public void Disconnect(string out_port_name,ProcessNode node,string in_port_name) {
            var out_port = GetPort(out_port_name);
            var in_port = node.GetPort(in_port_name);
            if(out_port == null || in_port == null) return;
            out_port.RemoveChild(in_port);
        }
    }
}